home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / program / smixw130.zip / SMIX.C < prev    next >
C/C++ Source or Header  |  1997-06-06  |  23KB  |  901 lines

  1. /*      SMIXW is Copyright 1995 by Ethan Brodsky.  All rights reserved      */
  2.  
  3. /* █ smix.c v1.30 █████████████████████████████████████████████████████████ */
  4.  
  5. #define TRUE  1
  6. #define FALSE 0
  7.  
  8. #define ON  1
  9. #define OFF 0
  10.  
  11. #define BLOCK_LENGTH    512   /* Length of digitized sound output block     */
  12. #define VOICES          8     /* Number of available simultaneous voices    */
  13. #define VOLUMES         64    /* Number of volume levels for sound output   */
  14. #define SAMPLING_RATE   22050 /* Sampling rate for output                   */
  15. #define SHIFT_16_BIT    5     /* Bits to shift left for 16-bit output       */
  16.  
  17. typedef struct
  18.   {
  19.     signed   char *soundptr;
  20.     unsigned long soundsize;
  21.   } SOUND;
  22.  
  23. int  init_sb(int baseio, int irq, int dma, int dma16);
  24. void shutdown_sb(void);
  25.  
  26. void set_sampling_rate(unsigned short rate);
  27.  
  28. void init_mixing(void);
  29. void shutdown_mixing(void);
  30.  
  31. int  open_sound_resource_file(char *filename);
  32. void close_sound_resource_file(void);
  33.  
  34. int  load_sound(SOUND **sound, char *key);
  35. void free_sound(SOUND **sound);
  36.  
  37. int  start_sound(SOUND *sound, int index, unsigned char volume, int loop);
  38. void stop_sound(int index);
  39. int  sound_playing(int index);
  40.  
  41. void set_sound_volume(unsigned char new_volume);
  42.  
  43. volatile long intcount;               /* Current count of sound interrupts  */
  44. volatile int  voicecount;             /* Number of voices currently in use  */
  45.  
  46. short dspversion;
  47. int   autoinit;
  48. int   sixteenbit;
  49. int   smix_sound;
  50.  
  51. /* ████████████████████████████████████████████████████████████████████████ */
  52.  
  53. #include <conio.h>
  54. #include <dos.h>
  55. #include <i86.h>
  56. #include <stdio.h>
  57. #include <stdlib.h>
  58. #include <string.h>
  59.  
  60. #include "lowmem.h"
  61.  
  62. #define BUFFER_LENGTH BLOCK_LENGTH*2
  63.  
  64. #define BYTE unsigned char
  65.  
  66. #define lo(value) (unsigned char)((value) & 0x00FF)
  67. #define hi(value) (unsigned char)((value) >> 8)
  68.  
  69. #define MAX(a, b) (((a) > (b)) ? (a) : (b))
  70. #define MIN(a, b) (((a) > (b)) ? (b) : (a))
  71.  
  72. static int resetport;
  73. static int readport;
  74. static int writeport;
  75. static int pollport;
  76. static int ackport;
  77.  
  78. static int pic_rotateport;
  79. static int pic_maskport;
  80.  
  81. static int dma_maskport;
  82. static int dma_clrptrport;
  83. static int dma_modeport;
  84. static int dma_addrport;
  85. static int dma_countport;
  86. static int dma_pageport;
  87.  
  88. static char irq_startmask;
  89. static char irq_stopmask;
  90. static char irq_intvector;
  91.  
  92. static char dma_startmask;
  93. static char dma_stopmask;
  94. static char dma_mode;
  95. static int  dma_length;
  96.  
  97. static void (interrupt far *oldintvector)(void);
  98.  
  99. static int smix_initialized  = FALSE;
  100. static int handler_installed = FALSE;
  101.  
  102. static int sampling_rate = SAMPLING_RATE;
  103.  
  104. static void write_dsp(BYTE value)
  105.   {
  106.     while ((inp(writeport) & 0x80));
  107.     outp(writeport, value);
  108.   }
  109.  
  110. static BYTE read_dsp(void)
  111.   {
  112.     while (!(inp(pollport) & 0x80));
  113.     return(inp(readport));
  114.   }
  115.  
  116. static int reset_dsp(void)
  117.   {
  118.     int i;
  119.  
  120.     outp(resetport, 1);
  121.     for (i=0; i < 100; i++)    /* The delay function doesn't work correctly */
  122.       { };
  123.     outp(resetport, 0);
  124.  
  125.     i = 100;
  126.     while ((i-- > 0) && (read_dsp() != 0xAA));
  127.  
  128.     return(i > 0);
  129.   }
  130.  
  131. void install_handler(void);
  132. void uninstall_handler(void);
  133. void smix_exitproc(void);
  134.  
  135. int init_sb(int baseio, int irq, int dma, int dma16)
  136.   {
  137.    /* Sound card IO ports */
  138.     resetport  = baseio + 0x006;
  139.     readport   = baseio + 0x00A;
  140.     writeport  = baseio + 0x00C;
  141.     pollport   = baseio + 0x00E;
  142.  
  143.    /* Reset DSP, get version, choose output mode */
  144.     if (!reset_dsp())
  145.       return(FALSE);
  146.     write_dsp(0xE1);  /* Get DSP version number */
  147.     dspversion = read_dsp() << 8;  dspversion += read_dsp();
  148.     autoinit   = (dspversion >= 0x0200);
  149.     sixteenbit = (dspversion >= 0x0400) && (dma16 != 0) && (dma16 > 3);
  150.  
  151.    /* Compute interrupt controller ports and parameters */
  152.     if (irq < 8)
  153.       { /* PIC1 */
  154.         irq_intvector  = 0x08 + irq;
  155.         pic_rotateport = 0x20;
  156.         pic_maskport   = 0x21;
  157.       }
  158.     else
  159.       { /* PIC2 */
  160.         irq_intvector  = 0x70 + irq-8;
  161.         pic_rotateport = 0xA0;
  162.         pic_maskport   = 0xA1;
  163.       }
  164.     irq_stopmask  = 1 << (irq % 8);
  165.     irq_startmask = ~irq_stopmask;
  166.  
  167.    /* Compute DMA controller ports and parameters */
  168.     if (sixteenbit)
  169.       { /* Sixteen bit */
  170.         dma_maskport   = 0xD4;
  171.         dma_clrptrport = 0xD8;
  172.         dma_modeport   = 0xD6;
  173.         dma_addrport   = 0xC0 + 4*(dma16-4);
  174.         dma_countport  = 0xC2 + 4*(dma16-4);
  175.         switch (dma16)
  176.           {
  177.             case 5:
  178.               dma_pageport = 0x8B;
  179.               break;
  180.             case 6:
  181.               dma_pageport = 0x89;
  182.               break;
  183.             case 7:
  184.               dma_pageport = 0x8A;
  185.               break;
  186.           }
  187.         dma_stopmask  = dma16-4 + 0x04;  /* 000001xx */
  188.         dma_startmask = dma16-4 + 0x00;  /* 000000xx */
  189.         if (autoinit)
  190.           dma_mode = dma16-4 + 0x58;     /* 010110xx */
  191.         else
  192.           dma_mode = dma16-4 + 0x48;     /* 010010xx */
  193.         ackport = baseio + 0x00F;
  194.       }
  195.     else
  196.       { /* Eight bit */
  197.         dma_maskport   = 0x0A;
  198.         dma_clrptrport = 0x0C;
  199.         dma_modeport   = 0x0B;
  200.         dma_addrport   = 0x00 + 2*dma;
  201.         dma_countport  = 0x01 + 2*dma;
  202.         switch (dma)
  203.           {
  204.             case 0:
  205.               dma_pageport = 0x87;
  206.               break;
  207.             case 1:
  208.               dma_pageport = 0x83;
  209.               break;
  210.             case 2:
  211.               dma_pageport = 0x81;
  212.               break;
  213.             case 3:
  214.               dma_pageport = 0x82;
  215.               break;
  216.           }
  217.         dma_stopmask  = dma + 0x04;      /* 000001xx */
  218.         dma_startmask = dma + 0x00;      /* 000000xx */
  219.         if (autoinit)
  220.           dma_mode    = dma + 0x58;      /* 010110xx */
  221.         else
  222.           dma_mode    = dma + 0x48;      /* 010010xx */
  223.         ackport = baseio + 0x00E;
  224.       }
  225.  
  226.     if (autoinit)
  227.       dma_length = BUFFER_LENGTH;
  228.     else
  229.       dma_length = BLOCK_LENGTH;
  230.  
  231.     install_handler();
  232.  
  233.     smix_initialized = FALSE;
  234.     smix_sound = FALSE;
  235.  
  236.     atexit(smix_exitproc);
  237.  
  238.     return(TRUE);
  239.   }
  240.  
  241. void shutdown_sb(void)
  242.   {
  243.     if (handler_installed) uninstall_handler();
  244.     reset_dsp();
  245.   }
  246.  
  247. /* Voice control */
  248.  
  249. typedef struct
  250.   {
  251.     SOUND *sound;
  252.     int   index;
  253.     int   volume;
  254.     int   loop;
  255.     long  curpos;
  256.     int   done;
  257.   } VOICE;
  258.  
  259. static int   inuse[VOICES];
  260. static VOICE voice[VOICES];
  261.  
  262. static int curblock;
  263.  
  264. /* Volume lookup table */
  265. static signed int (*volume_table)[VOLUMES][256];
  266.  
  267. /* Mixing buffer */
  268. static signed int  mixingblock[BLOCK_LENGTH];  /* Signed 16 bit */
  269.  
  270. /* Output buffers */
  271. static void          (*outmemarea)                = NULL;
  272. static unsigned char (*out8buf)[2][BLOCK_LENGTH]  = NULL;
  273. static signed  short (*out16buf)[2][BLOCK_LENGTH] = NULL;
  274.  
  275. static void *blockptr[2];
  276.  
  277. static short int outmemarea_sel;              /* Selector for output buffer */
  278.  
  279. /* Addressing for auto-initialized transfers (Whole buffer)   */
  280. static unsigned long buffer_addr;
  281. static unsigned char buffer_page;
  282. static unsigned int  buffer_ofs;
  283.  
  284. /* Addressing for single-cycle transfers (One block at a time */
  285. static unsigned long block_addr[2];
  286. static unsigned char block_page[2];
  287. static unsigned int  block_ofs[2];
  288.  
  289. static unsigned char sound_volume;
  290.  
  291. /* 8-bit clipping */
  292.  
  293. static unsigned char (*clip_8_buf)[256*VOICES];
  294. static unsigned char (*clip_8)[256*VOICES];
  295.  
  296. static char time_constant(int rate)
  297.   {
  298.     return (256 - (1000000 / rate));
  299.   }
  300.  
  301. static void init_sampling_rate(unsigned short rate)
  302.   {
  303.     if (sixteenbit)
  304.       {
  305.         write_dsp(0x41);        /* Set digitized sound output sampling rate */
  306.         write_dsp(hi(rate));
  307.         write_dsp(lo(rate));
  308.       }
  309.     else
  310.       {
  311.         write_dsp(0x40);        /* Set digitized sound time constant        */
  312.         write_dsp(time_constant(rate));
  313.       }
  314.   }
  315.  
  316. void set_sampling_rate(unsigned short rate)
  317.   {
  318.     sampling_rate = rate;
  319.  
  320.     if (smix_sound)
  321.       {
  322.         if (sixteenbit)
  323.           {
  324.             init_sampling_rate(sampling_rate);
  325.             write_dsp(0xD6);    /* Continue 16-bit DMA mode digitized sound */
  326.           }
  327.         else
  328.           {
  329.             write_dsp(0xD0);    /* Pause 8-bit DMA mode digitized sound     */
  330.             init_sampling_rate(sampling_rate);
  331.             write_dsp(0xD4);    /* Continue 8-bit DMA mode digitized sound  */
  332.           }
  333.       }
  334.   }
  335.  
  336. static void start_dac(void)
  337.   {
  338.     outp(dma_maskport,   dma_stopmask);
  339.     outp(dma_clrptrport, 0x00);
  340.     outp(dma_modeport,   dma_mode);
  341.     outp(dma_addrport,   lo(buffer_ofs));
  342.     outp(dma_addrport,   hi(buffer_ofs));
  343.     outp(dma_countport,  lo(dma_length-1));
  344.     outp(dma_countport,  hi(dma_length-1));
  345.     outp(dma_pageport,   buffer_page);
  346.     outp(dma_maskport,   dma_startmask);
  347.  
  348.     init_sampling_rate(sampling_rate);
  349.  
  350.     if (sixteenbit)
  351.       { /* Sixteen bit auto-initialized: SB16 and up (DSP 4.xx)             */
  352.         write_dsp(0xB6);                /* 16-bit cmd  - D/A - A/I - FIFO   */
  353.         write_dsp(0x10);                /* 16-bit mode - signed mono        */
  354.         write_dsp(lo(BLOCK_LENGTH-1));
  355.         write_dsp(hi(BLOCK_LENGTH-1));
  356.       }
  357.     else
  358.       { /* Eight bit */
  359.         write_dsp(0xD1);                /* Turn on speaker                  */
  360.  
  361.         if (autoinit)
  362.           { /* Eight bit auto-initialized:  SBPro and up (DSP 2.00+)        */
  363.             write_dsp(0x48);            /* Set DSP block transfer size      */
  364.             write_dsp(lo(BLOCK_LENGTH-1));
  365.             write_dsp(hi(BLOCK_LENGTH-1));
  366.             write_dsp(0x1C);            /* 8-bit auto-init DMA mono output  */
  367.           }
  368.         else
  369.           { /* Eight bit single-cycle:  Sound Blaster (DSP 1.xx+)           */
  370.             write_dsp(0x14);            /* 8-bit single-cycle DMA output    */
  371.             write_dsp(lo(BLOCK_LENGTH-1));
  372.             write_dsp(hi(BLOCK_LENGTH-1));
  373.           }
  374.       }
  375.  
  376.     smix_sound = TRUE;
  377.   }
  378.  
  379. static void stop_dac(void)
  380.   {
  381.     smix_sound = FALSE;
  382.  
  383.     if (sixteenbit)
  384.       {
  385.         write_dsp(0xD5);                /* Pause 16-bit DMA sound I/O       */
  386.       }
  387.     else
  388.       {
  389.         write_dsp(0xD0);                /* Pause 8-bit DMA sound I/O        */
  390.         write_dsp(0xD3);                /* Turn off speaker                 */
  391.       }
  392.  
  393.     outp(dma_maskport, dma_stopmask);   /* Stop DMA                         */
  394.   }
  395.  
  396. /* Volume control */
  397.  
  398. static void init_volume_table(void)
  399.   {
  400.     long volume;
  401.     int  insample;
  402.  
  403.     volume_table = malloc(VOLUMES * 256 * sizeof(signed int));
  404.  
  405.     for (volume=0; volume < VOLUMES; volume++)
  406.       for (insample = -128; insample <= 127; insample++)
  407.         {
  408.           (*volume_table)[volume][(unsigned char)insample] =
  409.             (signed int)(((insample*volume) << SHIFT_16_BIT) / (VOLUMES-1));
  410.         }
  411.  
  412.     sound_volume = 255;
  413.   }
  414.  
  415. void set_sound_volume(unsigned char new_volume)
  416.   {
  417.     sound_volume = new_volume;
  418.   }
  419.  
  420. /* Mixing initialization */
  421.  
  422. static void init_clip8(void)
  423.   {
  424.     int i;
  425.     int value;
  426.  
  427.     clip_8_buf = malloc(256*VOICES);
  428.     clip_8     = (char *)clip_8_buf + 128*VOICES;
  429.  
  430.     for (i = -128*VOICES; i < 128*VOICES; i++)
  431.       {
  432.         value = i;
  433.         value = MAX(value, -128);
  434.         value = MIN(value, 127);
  435.  
  436.         (*clip_8)[i] = value + 128;
  437.       }
  438.   }
  439.  
  440. static unsigned long linear_addr(void *ptr)
  441.   {
  442.     return((unsigned long)(ptr));
  443.   }
  444.  
  445. void deallocate_voice(int voicenum);
  446.  
  447. void init_mixing(void)
  448.   {
  449.     int i;
  450.  
  451.     for (i=0; i < VOICES; i++)
  452.       deallocate_voice(i);
  453.     voicecount = 0;
  454.  
  455.     if (sixteenbit)
  456.       {
  457.        /* Find a block of memory that does not cross a page boundary */
  458.         out16buf = outmemarea =
  459.           low_malloc(4*BUFFER_LENGTH, &outmemarea_sel);
  460.  
  461.         if ((((linear_addr(out16buf) >> 1) % 65536) + BUFFER_LENGTH) > 65536)
  462.           out16buf += 1;  /* Choose second half of memory area */
  463.  
  464.         for (i=0; i<2; i++)
  465.           blockptr[i] = &((*out16buf)[i]);
  466.  
  467.        /* DMA parameters */
  468.         buffer_addr = linear_addr(out16buf);
  469.         buffer_page = buffer_addr        / 65536;
  470.         buffer_ofs  = (buffer_addr >> 1) % 65536;
  471.  
  472.         memset(out16buf, 0x00, BUFFER_LENGTH * sizeof(signed short));
  473.       }
  474.     else
  475.       {
  476.        /* Find a block of memory that does not cross a page boundary */
  477.         out8buf = outmemarea =
  478.           low_malloc(2*BUFFER_LENGTH, &outmemarea_sel);
  479.  
  480.         if (((linear_addr(out8buf) % 65536) + BUFFER_LENGTH) > 65536)
  481.           out8buf += 1;  /* Choose second half of memory area */
  482.  
  483.         for (i=0; i<2; i++)
  484.           blockptr[i] = &((*out8buf)[i]);
  485.  
  486.        /* DMA parameters */
  487.         buffer_addr = linear_addr(out8buf);
  488.         buffer_page = buffer_addr / 65536;
  489.         buffer_ofs  = buffer_addr % 65536;
  490.         for (i=0; i<2; i++)
  491.           {
  492.             block_addr[i] = linear_addr(blockptr[i]);
  493.             block_page[i] = block_addr[i] / 65536;
  494.             block_ofs[i]  = block_addr[i] % 65536;
  495.           }
  496.         memset(out8buf, 0x80, BUFFER_LENGTH * sizeof(unsigned char));
  497.  
  498.         init_clip8();
  499.  
  500.       }
  501.  
  502.     curblock = 0;
  503.     intcount = 0;
  504.  
  505.     init_volume_table();
  506.     start_dac();
  507.   }
  508.  
  509. void shutdown_mixing(void)
  510.   {
  511.     stop_dac();
  512.  
  513.     free(volume_table);
  514.  
  515.     if (!sixteenbit) free(clip_8_buf);
  516.  
  517.     low_free(outmemarea_sel);
  518.   }
  519.  
  520. /* Setup for sound resource files */
  521.  
  522. static int  resource_file = FALSE;
  523. static char resource_filename[64] = "";
  524.  
  525. int fexist(char *filename)
  526.   {
  527.     FILE *f;
  528.  
  529.     f = fopen(filename, "r");
  530.  
  531.     fclose(f);
  532.  
  533.     return (f != NULL);
  534.   }
  535.  
  536. int  open_sound_resource_file(char *filename)
  537.   {
  538.     resource_file = TRUE;
  539.     strcpy(resource_filename, filename);
  540.  
  541.     return fexist(filename);
  542.   }
  543.  
  544. void close_sound_resource_file(void)
  545.   {
  546.     resource_file = FALSE;
  547.     strcpy(resource_filename, "");
  548.   }
  549.  
  550.  
  551. /* Loading and freeing sounds */
  552.  
  553. static FILE *sound_file;
  554. static long sound_size;
  555.  
  556. typedef struct
  557.   {
  558.     char key[8];
  559.     long start;
  560.     long size;
  561.   } RESOURCE_HEADER;
  562.  
  563. void get_sound_file(char *key)
  564.   {
  565.     static short numsounds;
  566.     int   found;
  567.     int   i;
  568.     static RESOURCE_HEADER res_header;
  569.  
  570.     found = FALSE;
  571.     sound_size = 0;
  572.  
  573.     if (resource_file)
  574.       {
  575.         sound_file = fopen(resource_filename, "rb");
  576.         fread(&numsounds, sizeof(numsounds), 1, sound_file);
  577.  
  578.         for (i = 0; i < numsounds; i++)
  579.           {
  580.             fread(&res_header, sizeof(res_header), 1, sound_file);
  581.             if (!strnicmp(key, res_header.key, 8))
  582.               {
  583.                 found = TRUE;
  584.                 break;
  585.               }
  586.           }
  587.  
  588.         if (found)
  589.           {
  590.             fseek(sound_file, res_header.start, SEEK_SET);
  591.             sound_size = res_header.size;
  592.           }
  593.       }
  594.     else
  595.       {
  596.         sound_file = fopen(key, "rb");
  597.         fseek(sound_file, 0, SEEK_END);
  598.         sound_size = ftell(sound_file);
  599.         fseek(sound_file, 0, SEEK_SET);
  600.       }
  601.   }
  602.  
  603. /* Loading and freeing sounds */
  604.  
  605. int load_sound(SOUND **sound, char *key)
  606.   {
  607.    /* Open file and compute size */
  608.     get_sound_file(key);
  609.  
  610.     if (sound_size == 0)
  611.       return FALSE;
  612.  
  613.    /* Allocate sound control structure and sound data block */
  614.     (*sound) = (SOUND *) malloc(sizeof(SOUND));
  615.     (*sound)->soundptr  = (signed char *)(malloc(sound_size));
  616.     (*sound)->soundsize = sound_size;
  617.  
  618.    /* Read sound data and close file (Isn't flat mode nice?) */
  619.     fread((*sound)->soundptr, sizeof(signed char), sound_size, sound_file);
  620.     fclose(sound_file);
  621.  
  622.     return TRUE;
  623.   }
  624.  
  625. void free_sound(SOUND **sound)
  626.   {
  627.     free((*sound)->soundptr);
  628.     free(*sound);
  629.     *sound = NULL;
  630.   }
  631.  
  632. /* Voice maintainance */
  633.  
  634. static void deallocate_voice(int voicenum)
  635.   {
  636.     inuse[voicenum] = FALSE;
  637.     voice[voicenum].sound  = NULL;
  638.     voice[voicenum].index  = -1;
  639.     voice[voicenum].volume = 0;
  640.     voice[voicenum].curpos = -1;
  641.     voice[voicenum].loop   = FALSE;
  642.     voice[voicenum].done   = FALSE;
  643.   }
  644.  
  645. int start_sound(SOUND *sound, int index, unsigned char volume, int loop)
  646.   {
  647.     int i, voicenum;
  648.  
  649.     voicenum = -1;
  650.     i = 0;
  651.  
  652.     do
  653.       {
  654.         if (!inuse[i])
  655.           voicenum = i;
  656.         i++;
  657.       }
  658.     while ((voicenum == -1) && (i < VOICES));
  659.  
  660.     if (voicenum != -1)
  661.       {
  662.         voice[voicenum].sound  = sound;
  663.         voice[voicenum].index  = index;
  664.         voice[voicenum].volume = volume;
  665.         voice[voicenum].curpos = 0;
  666.         voice[voicenum].loop   = loop;
  667.         voice[voicenum].done   = FALSE;
  668.  
  669.         inuse[voicenum] = TRUE;
  670.         voicecount++;
  671.       }
  672.  
  673.     return (voicenum != -1);
  674.   }
  675.  
  676. void stop_sound(int index)
  677.   {
  678.     int i;
  679.  
  680.     for (i=0; i < VOICES; i++)
  681.       if (voice[i].index == index)
  682.         {
  683.           voicecount--;
  684.           deallocate_voice(i);
  685.         }
  686.   }
  687.  
  688. int  sound_playing(int index)
  689.   {
  690.     int i;
  691.  
  692.    /* Search for a sound with the specified index */
  693.     for (i=0; i < VOICES; i++)
  694.       if (voice[i].index == index)
  695.         return(TRUE);
  696.  
  697.    /* Sound not found */
  698.     return(FALSE);
  699.   }
  700.  
  701. static void update_voices(void)
  702.   {
  703.     int voicenum;
  704.  
  705.     for (voicenum=0; voicenum < VOICES; voicenum++)
  706.       {
  707.         if (inuse[voicenum])
  708.           {
  709.             if (voice[voicenum].done)
  710.               {
  711.                 voicecount--;
  712.                 deallocate_voice(voicenum);
  713.               }
  714.           }
  715.       }
  716.   }
  717.  
  718. /* Mixing */
  719.  
  720. static void mix_voice(int voicenum)
  721.   {
  722.     SOUND *sound;
  723.     int   mixlength;
  724.     signed char *sourceptr;
  725.     signed int *volume_lookup;
  726.     int chunklength;
  727.     int destindex;
  728.  
  729.    /* Initialization */
  730.     sound = voice[voicenum].sound;
  731.  
  732.     sourceptr = sound->soundptr + voice[voicenum].curpos;
  733.     destindex = 0;
  734.  
  735.    /* Compute mix length */
  736.     if (voice[voicenum].loop)
  737.       mixlength = BLOCK_LENGTH;
  738.     else
  739.       mixlength =
  740.        MIN(BLOCK_LENGTH, sound->soundsize - voice[voicenum].curpos);
  741.  
  742.     volume_lookup =
  743.       (signed int *)(&(*volume_table)[(unsigned char)((sound_volume*voice[voicenum].volume*VOLUMES) >> 16)]);
  744.  
  745.     do
  746.       {
  747.        /* Compute the max consecutive samples that can be mixed */
  748.         chunklength =
  749.          MIN(mixlength, sound->soundsize - voice[voicenum].curpos);
  750.  
  751.        /* Update the current position */
  752.         voice[voicenum].curpos += chunklength;
  753.  
  754.        /* Update the remaining samples count */
  755.         mixlength -= chunklength;
  756.  
  757.        /* Mix samples until end of mixing or end of sound data is reached */
  758.         while (chunklength--)
  759.           mixingblock[destindex++] += volume_lookup[(unsigned char)(*(sourceptr++))];
  760.  
  761.        /* If we've reached the end of the block, wrap to start of sound */
  762.         if (sourceptr == (sound->soundptr + sound->soundsize))
  763.           {
  764.             if (voice[voicenum].loop)
  765.               {
  766.                 voice[voicenum].curpos = 0;
  767.                 sourceptr = sound->soundptr;
  768.               }
  769.             else
  770.               {
  771.                 voice[voicenum].done = TRUE;
  772.               }
  773.           }
  774.       }
  775.     while (mixlength); /* Wrap around to finish mixing if necessary */
  776.   }
  777.  
  778. static void silenceblock(void)
  779.   {
  780.     memset(&mixingblock, 0x00, BLOCK_LENGTH*sizeof(signed int));
  781.   }
  782.  
  783. static void mix_voices(void)
  784.   {
  785.     int i;
  786.  
  787.     silenceblock();
  788.  
  789.     for (i=0; i < VOICES; i++)
  790.       if (inuse[i])
  791.         mix_voice(i);
  792.   }
  793.  
  794. static void copy_sound16(void)
  795.   {
  796.     int i;
  797.     signed short *destptr;
  798.  
  799.     destptr   = blockptr[curblock];
  800.  
  801.     for (i=0; i < BLOCK_LENGTH; i++)
  802.       destptr[i] = mixingblock[i];
  803.   }
  804.  
  805. static void copy_sound8(void)
  806.   {
  807.     int i;
  808.     unsigned char *destptr;
  809.  
  810.     destptr   = blockptr[curblock];
  811.  
  812.     for (i=0; i < BLOCK_LENGTH; i++)
  813.       destptr[i] = (*clip_8)[mixingblock[i] >> 5];
  814.   }
  815.  
  816. static void copy_sound(void)
  817.   {
  818.     if (sixteenbit)
  819.       copy_sound16();
  820.     else
  821.       copy_sound8();
  822.   }
  823.  
  824. static void startblock_sc(void)     /* Starts a single-cycle DMA transfer   */
  825.   {
  826.     outp(dma_maskport,   dma_stopmask);
  827.     outp(dma_clrptrport, 0x00);
  828.     outp(dma_modeport,   dma_mode);
  829.     outp(dma_addrport,   lo(block_ofs[curblock]));
  830.     outp(dma_addrport,   hi(block_ofs[curblock]));
  831.     outp(dma_countport,  lo(BLOCK_LENGTH-1));
  832.     outp(dma_countport,  hi(BLOCK_LENGTH-1));
  833.     outp(dma_pageport,   block_page[curblock]);
  834.     outp(dma_maskport,   dma_startmask);
  835.     write_dsp(0x14);                /* 8-bit single-cycle DMA sound output  */
  836.     write_dsp(lo(BLOCK_LENGTH-1));
  837.     write_dsp(hi(BLOCK_LENGTH-1));
  838.   }
  839.  
  840. static void interrupt inthandler(void)
  841.   {
  842.     intcount++;
  843.  
  844.     if (!autoinit)   /* Start next block quickly if not using auto-init DMA */
  845.       {
  846.         startblock_sc();
  847.         copy_sound();
  848.         curblock = !curblock;  /* Toggle block */
  849.       }
  850.  
  851.     update_voices();
  852.     mix_voices();
  853.  
  854.     if (autoinit)
  855.       {
  856.         copy_sound();
  857.         curblock = !curblock;  /* Toggle block */
  858.       }
  859.  
  860.     inp(ackport);       /* Acknowledge interrupt with sound card */
  861.     outp(0xA0, 0x20);   /* Acknowledge interrupt with PIC2 */
  862.     outp(0x20, 0x20);   /* Acknowledge interrupt with PIC1 */
  863.   }
  864.  
  865. static void install_handler(void)
  866.   {
  867.     _disable();  /* CLI */
  868.     outp(pic_maskport, (inp(pic_maskport) | irq_stopmask));
  869.  
  870.     oldintvector = _dos_getvect(irq_intvector);
  871.     _dos_setvect(irq_intvector, inthandler);
  872.  
  873.     outp(pic_maskport, (inp(pic_maskport) & irq_startmask));
  874.     _enable();   /* STI */
  875.  
  876.     handler_installed = TRUE;
  877.   }
  878.  
  879. static void uninstall_handler(void)
  880.   {
  881.     _disable();  /* CLI */
  882.     outp(pic_maskport, (inp(pic_maskport) | irq_stopmask));
  883.  
  884.     _dos_setvect(irq_intvector, oldintvector);
  885.  
  886.     _enable();   /* STI */
  887.  
  888.     handler_installed = FALSE;
  889.   }
  890.  
  891. static void smix_exitproc(void)
  892.   {
  893.     if (smix_initialized)
  894.       {
  895.         stop_dac();
  896.         shutdown_sb();
  897.       }
  898.   }
  899.  
  900. /* ████████████████████████████████████████████████████████████████████████ */
  901.